#include "nosal/core/abort.h"

#include <atomic>
#include <mutex>
#include <iostream>
#include <cstdlib>
#include <cassert>

namespace netaos {
namespace nosal {
namespace core {

static std::atomic<AbortHandler> g_abortHandler;

static std::mutex g_abortMutex;

AbortHandler SetAbortHandler(AbortHandler handler) noexcept
{
    assert(g_abortHandler.is_lock_free());

    AbortHandler oldHandler = g_abortHandler.exchange(handler);
    return oldHandler;
}

void Abort(const char* text) noexcept
{
    std::lock_guard<std::mutex> lock{g_abortMutex};

    std::cerr << "Explicit Operation Abortion: " << text << "\n";

    AbortHandler const handler = g_abortHandler.load();
    if (handler != nullptr) {
        handler();
    }

    std::abort();
}

}  // namespace core
}  // namespace nosal
}  // namespace netaos
